# 类/方法：Table
from typing import Dict, List, Optional, Any, Tuple
from .field import Field, FieldType
from src.utils.parser import Parser

from src.utils.type_converter import TypeConverter

from src.utils.serializer import Serializer


class Table:
    """表类，维护表结构
    
    二进制结构：
    [TableName][NextTable][Field1Uid][Field2Uid]...[FieldNUid]
    """
    
    def __init__(self, table_manager, uid: int = 0):
        """初始化表对象
        
        Args:
            table_manager: 表管理器对象
            uid: 表的唯一标识符，默认为0（新表）
        """
        self.table_manager = table_manager
        self.uid = uid
        self.name = ""
        self.next_uid = 0
        self.fields: List[Field] = []
    

    @classmethod
    def create_table(cls, table_manager, next_uid: int, xid: int,
                    table_name: str, field_names: List[str], 
                    field_types: List[str], indexes: List[str]) -> 'Table':
        """创建新表
        
        创建表对象，添加字段，并将表元数据持久化到存储
        
        Args:
            table_manager: 表管理器对象
            next_uid: 下一个表的UID
            xid: 事务ID
            table_name: 表名
            field_names: 字段名列表
            field_types: 字段类型列表
            indexes: 需要创建索引的字段名列表
            
        Returns:
            创建的表对象
        """
        table = cls(table_manager)
        table.name = table_name
        table.next_uid = next_uid
        
        for field_name in field_names:
            if field_name in indexes:
                has_primary_key = True
                break
        
        # 创建字段
        for i, field_name in enumerate(field_names):
            field_type = field_types[i]
            indexed = field_name in indexes
            primary_key = field_name in indexes  # 简化处理，索引字段即为主键
            field = Field.create_field(table, xid, field_name, field_type, indexed, primary_key)
            table.fields.append(field)
        
        # 持久化表
        return table.persist_self(xid)
    # 解析表与持久化
    def _parse_self(self, raw: bytes) -> 'Table':
        """解析表数据
        
        从二进制数据解析表的元数据，包括表名、下一个表UID和字段列表
        
        Args:
            raw: 表的二进制数据
            
        Returns:
            解析后的表对象（self）
        """
        name,next_uid,uids = Serializer.deserialize_table_meta(raw)

        self.name = name
        self.next_uid = next_uid
        for field_uid in uids:
            field = Field.load_field(self, field_uid)
            self.fields.append(field)

        return self
    
    def persist_self(self, xid: int) -> 'Table':
        # 组合所有数据
        raw =  Serializer.serialize_table_meta(self)
        # 插入到存储中
        self.uid = self.table_manager.data_manager.insert(xid, raw)
        return self

    @classmethod
    def load_table(cls, table_manager, uid: int) -> 'Table':
        """从存储中加载表

        从存储系统中读取表的元数据并构造表对象

        Args:
            table_manager: 表管理器对象
            uid: 表的唯一标识符

        Returns:
            加载的表对象
        刚取出来不用persist
        Raises:
            Exception: 当表不存在时抛出异常
        """
        # 1.创建实例
        table = cls(table_manager, uid)
        # 2.解析数据
        di = table_manager.data_manager.read(uid)
        if di is None:
            raise Exception(f"Table with uid {uid} not found")
        raw = di.data()
        name, next_uid, uids = Serializer.deserialize_table_meta(raw.raw[raw.start:raw.end])
        # 赋值
        table.name = name
        table.next_uid = next_uid

        for field_uid in uids:
            field = Field.load_field(table, field_uid)
            table.fields.append(field)

        return table


    def insert(self, xid: int, values: List[str]) -> None:
        """插入记录
        
        将一组值插入表中作为新记录，并更新相关索引
        
        Args:
            xid: 事务ID
            values: 字段值列表，顺序与表字段定义一致
            
        Raises:
            ValueError: 当值的数量与字段数量不匹配时抛出异常
        """
        # 删除检查隐藏ID字段的代码
        # 不再处理隐藏ID字段
        # has_hidden_id = len(self.fields) > 0 and self.fields[0].name == "_id"
        # if has_hidden_id and len(values) == len(self.fields) - 1:
        #     next_id = self._get_next_id()
        #     values.insert(0, str(next_id))
        
        if len(values) != len(self.fields):
            raise ValueError(f"Expected {len(self.fields)} values, got {len(values)}")
        
        # 将字符串值转换为对应类型的字典
        entry = {}
        for i, field in enumerate(self.fields):
            entry[field.name] = values[i]
        # 序列化记录
        raw = self._entry_to_raw(entry)
        
        # 插入到存储中
        uid = self.table_manager.data_manager.insert(xid, raw)

        # 更新索引（如果有）
        for f in self.fields:
            f.insert(entry.get(f.name), uid)

    
    def read(self, uid:int) -> Optional[Any]:
        """读取记录并返回Tuple对象
        
        Args:
            uid: 记录的唯一标识符
            
        Returns:
            解析后的Tuple对象，如果记录不存在则返回None
        """
        from src.execution.executor import Tuple
        
        di = self.table_manager.data_manager.read(uid)
        if di is None:
            return None
        try:
            # subArray对象
            raw = di.data()
            # 一个字典，对应一行
            entry = self._parse_entry(raw.raw[raw.start:raw.end])

            # 构建返回的Tuple对象
            values = []
            schema_fields = []
            for field in self.fields:
                values.append(entry.get(field.name))
                schema_fields.append((field.name, field.field_type))

            from src.execution.executor import Schema, Tuple
            schema = Schema(schema_fields)
            
            return Tuple(schema, values)
        finally:
            # 释放缓存引用
            try:
                di.release()
            except:
                pass

    def select(self, xid: int,
            where_conditions: Dict = None) -> List[int]:
        """读取记录
        
        根据条件查询表中的记录并返回匹配的UID列表
        
        Args:
            xid: 事务ID
            where_conditions: 查询条件字典
            
        Returns:
            匹配的记录UID列表
        """
        return self._parse_where(where_conditions)
        
        uids = self._parse_where(where_conditions)
        result = []
        
        for uid in uids:
            di = self.table_manager.data_manager.read(uid)
            if di is None:
                continue
            
            try:
                raw = di.data()
                entry = self._parse_entry(raw.raw[raw.start:raw.end])
                result.append(self._format_entry(entry))
            finally:
                # 释放缓存引用
                try:
                    di.release()
                except:
                    pass
        
        return '\n'.join(result)
    
    def update(self, xid: int, set_values: Dict[str, str], 
              where_conditions: Dict = None) -> int:
        """更新记录
        
        根据条件更新表中的记录
        
        Args:
            xid: 事务ID
            set_values: 要设置的字段值字典，键为字段名，值为新值
            where_conditions: 查询条件字典
            
        Returns:
            更新的记录数量
            
        Raises:
            ValueError: 当指定的字段不存在时抛出异常
        """
        uids = self._parse_where(where_conditions)
        count = 0

            # 读取原始数据
        # 查找要更新的字段
        for field_name, value_str in set_values.items():
            field = self.get_field(field_name)
            if field is None:
                raise ValueError(f"Field {field_name} not found")
        
        # 更新每条记录
        for uid in uids:
            di = self.table_manager.data_manager.read(uid)
            if di is None:
                continue
            # 读取原始数据
            raw = di.data()
            entry = self._parse_entry(raw.raw[raw.start:raw.end])

            # 删除旧记录
            di.delete()

            # 更新字段值
            for field_name, value_str in set_values.items():
                field = self.get_field(field_name)
                entry[field.name] = TypeConverter.str_to_field_var(value_str, field.field_type)

            # 序列化并插入新记录
            new_raw = self._entry_to_raw(entry)
            uid = self.table_manager.data_manager.insert(xid, new_raw)

            # 更新索引（如果有）
            for f in self.fields:
                f.insert(entry.get(f.name), uid)
            count += 1


            # try:
            #     # 读取原始数据
            #     raw = di.data()
            #     entry = self._parse_entry(raw.raw[raw.start:raw.end])
            #
            #     # 删除旧记录
            #     di.delete()
            #
            #     # 更新字段值
            #     for field_name, value_str in set_values.items():
            #         field = self.get_field(field_name)
            #         entry[field.name] = TypeConverter.str_to_field_var(value_str, field.field_type)
            #
            #
            #     # 序列化并插入新记录
            #     new_raw = self._entry_to_raw(entry)
            #     new_uid = self.table_manager.data_manager.insert(xid, new_raw)
            #     self.insert(xid, new_uid)
            #
            #     count += 1
            # except Exception as e:
            #     print(f"更新记录失败: {e}")
        
        return count
    
    def delete(self, xid: int, where_conditions: Dict = None) -> int:
        """删除记录
        
        根据条件删除表中的记录
        
        Args:
            xid: 事务ID
            where_conditions: 查询条件字典
            
        Returns:
            删除的记录数量
        """
        uids = self._parse_where(where_conditions)
        count = 0
        
        for uid in uids:
            di = self.table_manager.data_manager.read(uid)

            if di is None:
                continue
            di.delete()
            di.release()
            count+=1
            # try:
            #     # 读取记录数据以便从索引中删除
            #     raw = di.data()
            #     entry = self._parse_entry(raw)
            #
            #     # 释放数据项
            #     self.table_manager.data_manager.release_data_item(di)
            #     count += 1
            # except Exception as e:
            #     print(f"删除记录失败: {e}")
        
        return count
    
    def delete_all(self, xid: int) -> int:
        """删除表中所有记录
        
        使用索引快速查找并删除表中的所有记录
        
        Args:
            xid: 事务ID
            
        Returns:
            删除的记录数量
        """
        # 找到所有索引字段
        indexed_fields = [field for field in self.fields if getattr(field, "indexed", False)]
        
        if not indexed_fields:
            # 如果没有索引字段，无法高效删除所有记录
            return 0
        
        # 使用第一个索引字段查找所有记录
        field = indexed_fields[0]
        uids = field.search(0, float('inf'))  # 使用最大范围查询所有记录
        
        return self.delete(xid, None)  # 复用delete方法删除所有记录
    
    def _entry_to_raw(self, entry: Dict[str, Any]) -> bytes:
        """将记录转换为字节数组
        
        将字段值字典序列化为二进制格式
        
        Args:
            entry: 字段值字典，键为字段名，值为字段值
            
        Returns:
            序列化后的字节数组
        """
        raw = b''
        for field in self.fields:
            value = entry.get(field.name)
            # 修正调用 serialize_value
            raw += field.serialize_value(value)
        return raw
    
    def _parse_entry(self, raw: bytes) -> Dict[str, Any]:
        """解析记录
        
        从二进制数据解析出字段值字典
        
        Args:
            raw: 记录的二进制数据
            
        Returns:
            解析后的字段值字典，键为字段名，值为字段值
        """
        entry = {}
        position = 0
        for field in self.fields:
            value, consumed = field.deserialize_value(raw[position:])
            entry[field.name] = value
            position += consumed
        return entry
    

    
    def _parse_where(self, where_conditions: Dict = None) -> List[int]:
        """解析where条件并返回匹配的记录UID列表
        
        根据查询条件使用索引查找匹配的记录
        支持单字段条件和多字段条件（AND逻辑）
        
        Args:
            where_conditions: 查询条件字典
            
        Returns:
            匹配的记录UID列表
            
        Raises:
            ValueError: 当字段不存在或不是索引字段时抛出异常
        """
        # 如果没有条件，尝试使用第一个索引字段查找所有记录
        if not where_conditions:
            # 返回所有记录
            all_uids = []
            for field in self.fields:
                if field.indexed:
                    # 使用一个很大的范围获取所有记录
                    all_uids = field.search(float('-inf'), float('inf'))
                    break
            return all_uids

        result_sets = []

        for field_name, condition in where_conditions.items():
            field = self.get_field(field_name)
            if field is None:
                raise ValueError(f"Field '{field_name}' not found")

            # 正确解包条件
            if isinstance(condition, tuple) and len(condition) == 2:
                op, value = condition
            else:
                # 默认为等于操作
                op = '='
                value = condition

            if not field.indexed:
                print(f"警告: 字段 '{field_name}' 没有索引，使用全表扫描")
                # 这里应该实现全表扫描逻辑
                continue

            try:
                # 使用field的calExp方法计算查询范围
                left_key, right_key = field.calExp(op, value)
                uids = field.search(left_key, right_key)
                result_sets.append(set(uids))
            except Exception as e:
                print(f"处理字段 '{field_name}' 的WHERE条件时出错: {e}")
                # 查询失败返回空集
                result_sets.append(set())

        # 取交集
        if not result_sets:
            return []

        result = result_sets[0]
        for s in result_sets[1:]:
            result &= s

        return list(result)
    
    def get_field(self, field_name: str) -> Optional[Field]:
        """根据字段名获取字段对象
        
        Args:
            field_name: 字段名
            
        Returns:
            字段对象，如果不存在则返回None
        """
        for f in self.fields:
            if f.name == field_name:
                return f
        return None

    def __str__(self) -> str:
        """返回表的字符串表示
        
        Returns:
            表的字符串表示，包含表名和字段信息
        """
        field_info = ', '.join([f"{f.name}({f.field_type.value if isinstance(f.field_type, FieldType) else f.field_type})" for f in self.fields])
        return f"{self.name}({field_info})"